package com.springboot.file.controller;

import cn.hutool.core.util.ObjectUtil;
import com.springboot.file.constant.Result;
import com.springboot.file.param.req.ExportExcelReq;
import com.springboot.file.param.req.ExportWordReq;
import com.springboot.file.param.resp.ExportExcelResp;
import com.springboot.file.service.CommonService;
import com.springboot.file.util.easyexcel.ExceptionUtils;
import com.springboot.file.util.easyexcel.exception.ExcelValidationException;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.LinkedHashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;

@RestController
@RequestMapping("/common")
@Tag(name ="通用工具管理")
public class CommonController {
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);

    @Resource
    private CommonService commonService;

    @PostMapping("/importExcel")
    @Operation(summary = "按业务类型导入各业务数据")
    public Result<Void> importExcel(@RequestParam("businessType") String businessType, @RequestParam("file") MultipartFile file) {
        try {
            commonService.importExcel(businessType, file);
            return Result.success();
        } catch (ExcelValidationException e) {
            // 直接使用异常中的完整错误消息
            ExceptionUtils.logValidationException(e, "Controller");
            return Result.error(e.getMessage());
        } catch (Exception e) {
            // 尝试提取验证异常
            Object validationExObj = ExceptionUtils.extractValidationException(e);
            if (validationExObj instanceof ExcelValidationException validationEx) {
                // 安全地转换为ExcelValidationException
                // 使用验证异常的详细信息
                ExceptionUtils.logValidationException(validationEx, "Controller-嵌套异常");
                return Result.error(validationEx.getMessage());
            }
            
            log.error("导入数据失败", e);
            // 获取最终的错误信息
            Throwable rootCause = ExceptionUtils.getRootCause(e);
            return Result.error("导入失败: " + (rootCause != null ? rootCause.getMessage() : e.getMessage()));
        }
    }

    @PostMapping("/importMultiSheetExcel")
    @Operation(summary = "导入多Sheet数据到不同表中",
            description = "业务类型字符串，支持以下格式:\n" +
                    "1. 带引号的逗号分隔格式: \"CUST_CREDIT\",\"INVOICE\"\n" +
                    "2. 不带引号的逗号分隔格式: CUST_CREDIT,INVOICE\n" +
                    "3. JSON数组格式: [\"CUST_CREDIT\",\"INVOICE\"]\n" +
                    "4. JSON对象格式: {\"CUST_CREDIT\",\"INVOICE\"}\n" +
                    "enableTransaction参数：是否启用事务管理，默认为false。当为true时，所有sheet的保存操作将在同一事务中进行，有错误时回滚所有操作"  )
    public Result<Void> importMultiSheetExcel(
            @RequestParam("businessTypes") String businessTypes,
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "enableTransaction", required = false, defaultValue = "false") Boolean enableTransaction) {
        if (ObjectUtil.isEmpty(businessTypes)) {
            return Result.error("业务类型不能为空");
        }
        try {
            commonService.importMultiSheetExcel(businessTypes, file, enableTransaction);
            return Result.success();
        } catch (ExcelValidationException e) {
            // 直接使用异常中的完整错误消息
            ExceptionUtils.logValidationException(e, "Controller-多Sheet");
            return Result.error(e.getMessage());
        } catch (Exception e) {
            // 尝试提取验证异常
            Object validationExObj = ExceptionUtils.extractValidationException(e);
            if (validationExObj instanceof ExcelValidationException validationEx) {
                // 安全地转换为ExcelValidationException
                // 使用验证异常的详细信息
                ExceptionUtils.logValidationException(validationEx, "Controller-多Sheet嵌套异常");
                return Result.error(validationEx.getMessage());
            }
            
            log.error("导入多Sheet数据失败", e);
            // 获取最终的错误信息
            Throwable rootCause = ExceptionUtils.getRootCause(e);
            return Result.error("导入失败: " + (rootCause != null ? rootCause.getMessage() : e.getMessage()));
        }
    }
    
    @PostMapping("/exportExcel")
    @Operation(summary = "按业务类型导出各业务数据")
    public void exportExcel(HttpServletResponse response, @RequestBody ExportExcelReq exportExcelReq) {
        // 如果没有传入导出条件，则创建一个空的Map
        Map<String, Object> exportParams = null;
        if (ObjectUtil.isEmpty(exportExcelReq.getExportParams())) {
            exportParams = new LinkedHashMap<>();
        }

        // 执行导出
        commonService.exportExcel(exportExcelReq.getBusinessType(), exportParams, exportExcelReq.getHeaders(), response);
    }

    /**
     * 清理临时文件
     * 用于前端在导出完成后清理服务器上的临时文件
     *
     * @param chunkId 文件ID，与导出时的chunkId相同
     * @return 清理结果
     */
    @PostMapping("/cleanupTempFile")
    @ApiOperation("清理临时文件")
    public Result<String> cleanupTempFile(@RequestParam("chunkId") String chunkId) {
        log.info("收到清理临时文件请求: chunkId={}", chunkId);
        
        try {
            if (chunkId == null || chunkId.isEmpty()) {
                return Result.error("文件ID不能为空");
            }
            
            boolean success = commonService.cleanupExportFile(chunkId);
            
            if (success) {
                return Result.success("临时文件清理成功");
            } else {
                return Result.error("找不到指定临时文件或清理失败");
            }
        } catch (Exception e) {
            log.error("清理临时文件失败", e);
            return Result.error("清理临时文件失败: " + e.getMessage());
        }
    }

    @PostMapping("/smartExportExcel")
    @Operation(summary = "智能Excel导出，根据数据量自动选择单文件或多文件导出")
    public Result<ExportExcelResp> smartExportExcel(HttpServletResponse response, @RequestBody ExportExcelReq exportExcelReq) {
        try {
            // 提取导出参数
            Map<String, Object> exportParams = exportExcelReq.getExportParams();
            if (exportParams == null) {
                exportParams = new HashMap<>();
            }
            
            // 提取文件名
            String fileName = exportExcelReq.getFileName();
            if (fileName == null || fileName.trim().isEmpty()) {
                fileName = "export";
            }
            
            // 执行智能导出
            ExportExcelResp result = commonService.smartExportExcel(
                    exportExcelReq.getBusinessType(),
                    exportParams,
                    exportExcelReq.getHeaders(),
                    fileName,
                    response
            );
            
            // 如果返回值为null，表示使用了普通导出（响应已直接写入response）
            if (result == null) {
                return null;
            }
            
            // 检查响应内容是否完整（如果是多文件/分块导出）
            if (result.getChunkId() == null || result.getChunkId().isEmpty()) {
                log.error("导出响应缺少chunkId字段");
                return Result.error("导出请求处理异常：响应格式不正确");
            }
            
            // 确保文件内容字段不为null
            if (result.getFileContent() == null) {
                log.error("导出响应缺少文件内容字段");
                return Result.error("导出请求处理异常：响应缺少文件内容");
            }
            
            // 返回成功响应
            log.info("智能导出成功: 文件名={}, 文件大小={}KB, 是否多文件={}, 文件索引={}/{}",
                    result.getFileName(),
                    result.getFileContent().length / 1024,
                    result.getIsMultiFileExport(),
                    result.getFileIndex(),
                    result.getTotalFiles());
                    
            return Result.success(result);
        } catch (Exception e) {
            log.error("智能导出Excel异常：", e);
            return Result.error("导出异常：" + e.getMessage());
        }
    }
    
    @PostMapping("/exportWord")
    @Operation(summary = "按模板导出Word文档",
            description = "根据指定的Word模板生成文档，支持自定义占位符、页眉页脚、水印等")
    public void exportWord(HttpServletResponse response, @RequestBody ExportWordReq exportWordReq) {
        try {
            log.info("收到Word文档导出请求: 业务类型={}, 模板={}, 文件名={}",
                    exportWordReq.getBusinessType(),
                    exportWordReq.getTemplateName(),
                    exportWordReq.getFileName());
            
            commonService.exportWord(exportWordReq, response);
        } catch (Exception e) {
            log.error("导出Word文档失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            try {
                response.getWriter().write("导出失败: " + e.getMessage());
            } catch (Exception ex) {
                log.error("写入错误响应失败", ex);
            }
        }
    }
    
    @PostMapping("/exportWordAsPdf")
    @Operation(summary = "按模板导出PDF文档",
            description = "根据指定的Word模板生成文档并转换为PDF，支持自定义占位符、页眉页脚、水印等")
    public void exportWordAsPdf(HttpServletResponse response, @RequestBody ExportWordReq exportWordReq) {
        try {
            log.info("收到PDF文档导出请求: 业务类型={}, 模板={}, 文件名={}",
                    exportWordReq.getBusinessType(),
                    exportWordReq.getTemplateName(),
                    exportWordReq.getFileName());
            
            commonService.exportWordAsPdf(exportWordReq, response);
        } catch (Exception e) {
            log.error("导出PDF文档失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            try {
                response.getWriter().write("导出失败: " + e.getMessage());
            } catch (Exception ex) {
                log.error("写入错误响应失败", ex);
            }
        }
    }
}
